package com.fcat.base.common.util;

import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import com.fcat.base.common.po.GpsPO;

public class PointUtil {
/*    private static final String BAIDU_AK = "fzthIZCp9lCB3pOXd5e7BhPwwTG4GEvn";*/

    private static double pi = 3.14159265358979324;
    private static double a = 6378245.0;
    private static double ee = 0.00669342162296594323;
    
    
    private PointUtil() {
    }

    /**
     * 返回坐标与 点的距离
     *
     * @param longitude
     * @param latitude
     * @param point
     * @return
     */
    public static double pointDistance(double longitude, double latitude, Point2D.Double point) {
        Point2D.Double point2D = new Point2D.Double(longitude, latitude);
        double distance = point2D.distance(point);
        return distance;
    }

    public static Point2D.Double getPoint(String longitude,String latitude){
        try {
            Point2D.Double point = new Point2D.Double(Double.parseDouble(longitude),Double.parseDouble(latitude));
            return point;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static List<Point2D.Double> getPointRange(String pointRange) {
        if (StrUtil.isBlank(pointRange)) {
            return null;
        }
        List<Point2D.Double> pointList = new ArrayList<>();
        if (!StrUtil.isBlank(pointRange)) {
            String[] point = pointRange.split(";");
            for (int i = 0; i < point.length; i++) {
                String[] pointArr = point[i].split(",");
                String longitudePoint = pointArr[0];
                String latitudePoint = pointArr[1];
                Point2D.Double point2D = new Point2D.Double(Double.parseDouble(longitudePoint),
                        Double.parseDouble(latitudePoint));
                pointList.add(point2D);
            }
        }
        return pointList;
    }

    /**
     *
     * @param longitude
     *            纬度
     * @param latitude
     *            精度
     * @param pointRange
     *            经纬度字符串
     * @return
     */
    public static boolean inRegion(double longitude, double latitude, String pointRange) {
        List<java.awt.geom.Point2D.Double> polygon = getPointRange(pointRange);
        /*to do if (CollectionUtils.isEmpty(polygon)) {
            return false;
        }*/
        Point2D.Double point = new Point2D.Double(longitude, latitude);
        GeneralPath p = new GeneralPath();
        Point2D.Double first = polygon.get(0);
        p.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            p.lineTo(d.x, d.y);
        }
        p.lineTo(first.x, first.y);
        p.closePath();
        return p.contains(point);
    }

    /**
     *
     * @param longitude
     *            纬度
     * @param latitude
     *            精度
     * @param jsonObject 格式：{type:'',point:""}
     *            经纬度字符串
     *type：
     *  polygon:多边形
     *  rectangle：矩形
     *  triangle：三角形
     *  circular：圆形
     * @return
     */
    //{"radius":58.8235294117647,"lat":22.61953775271929,"lng":114.03370569144181}
 /*   public static boolean inRegion(double longitude, double latitude, JSONObject jsonObject) {
        String type=jsonObject.getString("type");
        String pointRange=jsonObject.getString("point");
        if(type.equals("circular")){
            JSONObject obj=JSONObject.parseObject(pointRange);
            double radius=Double.parseDouble(obj.getString("radius"));
            double lat=Double.parseDouble(obj.getString("lat"));
            double lng=Double.parseDouble(obj.getString("lng"));
            double distance=getGoogleDistance(lat,latitude,lng,longitude);
            if(distance< radius){
                return true;
            }else{
                return false;
            }
        }else{
            List<java.awt.geom.Point2D.Double> polygon=null;
            polygon = getPointRange(pointRange);
            Point2D.Double point = new Point2D.Double(longitude, latitude);
            GeneralPath p = new GeneralPath();
            Point2D.Double first = polygon.get(0);
            p.moveTo(first.x, first.y);
            polygon.remove(0);
            for (Point2D.Double d : polygon) {
                p.lineTo(d.x, d.y);
            }
            p.lineTo(first.x, first.y);
            p.closePath();
            return p.contains(point);
        }
    }*/

    /**
     *
     * @param longitude
     *            纬度
     * @param latitude
     *            精度
     * @param polygon
     *            点列表
     * @return
     */
    public static boolean inRegion(double longitude, double latitude, List<Point2D.Double> polygon) {
        Point2D.Double point = new Point2D.Double(longitude, latitude);
        GeneralPath p = new GeneralPath();
        Point2D.Double first = polygon.get(0);
        p.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            p.lineTo(d.x, d.y);
        }

        p.lineTo(first.x, first.y);

        p.closePath();

        return p.contains(point);
    }

    /**
     * 判断点是否在区域内
     *
     * @param point
     * @param polygon
     * @return
     */
    public static boolean inRegion(Point2D.Double point, List<Point2D.Double> polygon) {
        GeneralPath p = new GeneralPath();

        Point2D.Double first = polygon.get(0);
        p.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            p.lineTo(d.x, d.y);
        }

        p.lineTo(first.x, first.y);

        p.closePath();
        polygon.add(first);
        return p.contains(point);
    }

    /**
     * 根据地址查询经纬度
     * @return
     */
/*    public static String getAddressByLngLat(String lng,String lat) {
        if(StrUtil.isEmpty(lng) || StrUtil.isEmpty(lat)){
            return null;
        }
        String latlngEncode = null;
        try {
            latlngEncode = java.net.URLEncoder.encode(lat + "," + lng, "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        String ak = "";//to do propertiesCache.get("baidu_ak");
        if(StrUtil.isEmpty(ak)){
            ak = BAIDU_AK;
        }
        String url = "http://api.map.baidu.com/geocoder/v2/?ak=" + ak + "&output=json" + "&location=" + latlngEncode;
        URL myURL = null;
        URLConnection httpsConn = null;
        JSONObject jsonObject = null;
        // 进行转码
        try {
            myURL = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            httpsConn = (URLConnection) myURL.openConnection();
            if (httpsConn != null) {
                InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
                BufferedReader br = new BufferedReader(insr);
                String message = "";
                String data = null;
                while ((data = br.readLine()) != null) {
                    message = message + data;
                }
                insr.close();
                if(!StrUtil.isBlank(message)){
                    jsonObject = JSONObject.parseObject(message);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        JSONObject resultJsonObject = jsonObject.getJSONObject("result");
        String address = null;
        if(resultJsonObject != null){
            address = resultJsonObject.getString("formatted_address");
        }
        return address;
    }*/

    public static String[] getLongitudeAndLatitude(String pointRange) {
        String[] lonAndLat = new String[2];
        String[] points = pointRange.split(";");
        double longitude=0,latitude=0;	//114.062138, 22.672331;114.084644, 22.684091;
        for (String string : points) {
            String[] pointsTmp=string.split(",");
            if(pointsTmp.length==2){
                longitude+=Double.parseDouble(pointsTmp[0]);
                latitude+=Double.parseDouble(pointsTmp[1]);
            }
        }
        longitude=longitude/points.length;
        latitude=latitude/points.length;
        lonAndLat[0]=String.format("%.6f", longitude);
        lonAndLat[1]=String.format("%.6f", latitude);
        return lonAndLat;
    }
    
    /**
     * 获取两个点之间的距离
     * @param lat1
     * @param lat2
     * @param lon1
     * @param lon2
     * @return
     */
    public static double getDistanceByPoint(double lat1, double lat2, double lon1, double lon2){
        double R = 6371;   
        double distance = 0.0;   
        double dLat = (lat2 - lat1) * Math.PI / 180;   
        double dLon = (lon2 - lon1) * Math.PI / 180;   
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)   
                + Math.cos(lat1 * Math.PI / 180)   
                * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2)   
                * Math.sin(dLon / 2);   
        distance = (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))) * R;   
        return distance;  
    }
    
    public static double getDistanceByPoint(String lat1, String lat2, String lon1, String lon2){
        Double latd1 = Double.parseDouble(lat1);
        Double latd2 = Double.parseDouble(lat1);
        Double lond1 = Double.parseDouble(lon1);
        Double lond2 = Double.parseDouble(lon2);
        return getDistanceByPoint(latd1,latd2,lond1,lond2);
    }
    /**
    *
    * @param slongitude
    *            纬度
    * @param slatitude
    *            精度
    * @param pointRange
    *            经纬度字符串
    * @return
    */
   public static boolean inRegion(String slongitude, String slatitude, String pointRange) {
	   double longitude=Double.parseDouble(slongitude);
	   double latitude=Double.parseDouble(slatitude);
	   
       List<java.awt.geom.Point2D.Double> polygon = getPointRange(pointRange);
       /*to do if (CollectionUtils.isEmpty(polygon)) {
           return false;
       }*/
       Point2D.Double point = new Point2D.Double(longitude, latitude);
       GeneralPath p = new GeneralPath();
       Point2D.Double first = polygon.get(0);
       p.moveTo(first.x, first.y);
       polygon.remove(0);
       for (Point2D.Double d : polygon) {
           p.lineTo(d.x, d.y);
       }
       p.lineTo(first.x, first.y);
       p.closePath();
       return p.contains(point);
   }
   
   /**
    * 地球坐标转换为火星坐标 World Geodetic System ==> Mars Geodetic System
    * 
    * @param wgLat
    *            地球坐标
    * @param wgLon
    * 
    *            mglat,mglon 火星坐标
    */
   public static GpsPO transform2Mars(double wgLat, double wgLon) {
       double mgLat, mgLon;
       double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
       double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
       double radLat = wgLat / 180.0 * pi;
       double magic = Math.sin(radLat);
       magic = 1 - ee * magic * magic;
       double sqrtMagic = Math.sqrt(magic);
       dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
       dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
       mgLat = wgLat + dLat;
       mgLon = wgLon + dLon;
       return new GpsPO(mgLon,mgLat);
   }

   private static double transformLat(double x, double y) {
       double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
       ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
       ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
       ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
       return ret;
   }

   private static double transformLon(double x, double y) {
       double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
       ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
       ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
       ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
       return ret;
   }
   
   
   public static void main(String[] args) {
       double distanceByPoint = getDistanceByPoint(22.5403999832, 22.5344162847, 114.0613559868, 114.0611001647);
       System.out.println(distanceByPoint);
   }



    /*
    获取谷歌地图上2个坐标点之间的距离，单位是米
     */
    public static double getGoogleDistance(double lati1,double lati2,double lng1,double lng2) {
        double lat1 = (Math.PI / 180) * lati1;
        double lat2 = (Math.PI / 180) * lati2;
        double lon1 = (Math.PI / 180) * lng1;
        double lon2 = (Math.PI / 180) * lng2;

        double R = 6371;//地球半径
        double d = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2)
                * Math.cos(lon2 - lon1))
                * R;
        return d * 1000;
    }
}
